package com.coocaa.x.service.liteupgrade;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import com.coocaa.x.framework.app.CoocaaApplication;
import com.coocaa.x.framework.data.JObject;
import com.coocaa.x.framework.utils.Android;
import com.coocaa.x.framework.utils.LiteHandlerThread;
import com.coocaa.x.framework.utils.LogUtils;
import com.duowan.mobile.netroid.Listener;
import com.duowan.mobile.netroid.NetroidError;
import com.duowan.mobile.netroid.Network;
import com.duowan.mobile.netroid.RequestQueue;
import com.duowan.mobile.netroid.cache.DiskCache;
import com.duowan.mobile.netroid.stack.HurlStack;
import com.duowan.mobile.netroid.toolbox.BasicNetwork;
import com.duowan.mobile.netroid.toolbox.FileDownloader;

import org.apache.http.protocol.HTTP;

import java.io.File;

/**
 * Created by lu on 15-6-18.
 */
public class LiteUpgradeDownloader {
    public static interface LiteUpgradeDownloaderListener {
        void onStart();

        void onProgress(int percent, long downloaded_length, long file_length);

        void onCancel();

        void onError(String e);

        void onSuccess(File f);
    }

    public static final String UPDATE_FILE = "update.apk";
    public static final String UPDATE_TEMP_FILE = "update.apk.tmp";

    private static final int TASK_SIZE = 2;
    private static FileDownloader filedownloader = null;
    private static RequestQueue mQueue = null;

    private static final String CONFIG_NAME = "upgrade";
    private static final String URL_KEY = "url";
    private static final String MD5_KEY = "md5";
    private static final String SAVE_PATH_KEY = "save";
    private static final String TEMP_PATH_KEY = "temp";

    private static SharedPreferences sp;

    private static String currentURL, currentMD5, currentSavePath, currentTempPath;

    static {
        sp = CoocaaApplication.getContext().getSharedPreferences(CONFIG_NAME, Context.MODE_WORLD_READABLE
                + Context.MODE_WORLD_WRITEABLE);
        currentURL = sp.getString(URL_KEY, "");
        currentMD5 = sp.getString(MD5_KEY, "");
        currentSavePath = sp.getString(SAVE_PATH_KEY, "");
        currentTempPath = sp.getString(TEMP_PATH_KEY, "");
        Network network = new BasicNetwork(new HurlStack("superx.cn", null), HTTP.UTF_8);
        mQueue = new RequestQueue(network, TASK_SIZE, new DiskCache(new File(CoocaaApplication.getContext().getCacheDir(), "cache")));
        mQueue.start();
        filedownloader = new FileDownloader(mQueue, 1);
    }

    private static FileDownloader getFileDownload() {
        return filedownloader;
    }

    private LiteUpgradeDownloaderListener listener = null;
    private FileDownloader.DownloadController dc = null;

    public LiteUpgradeDownloader() {
    }

    public void setListener(LiteUpgradeDownloaderListener l) {
        listener = l;
    }

    public synchronized void start(final File saveFile, final String url, final String md5) {
        LiteHandlerThread.postOnUiThread(new Runnable() {
            @Override
            public void run() {
                LogUtils.i("upgrade", "LiteUpgradeDownloader dc:" + dc + "   save_path:" + saveFile.getAbsolutePath() + "   url:" + url);
                if (!url.equals(currentURL)) {
                    cancel();
                }
                currentURL = url;
                currentMD5 = md5.toLowerCase();
                currentSavePath = saveFile.getAbsolutePath();
                currentTempPath = saveFile.getParentFile().getAbsolutePath() + File.separator + UPDATE_TEMP_FILE;
                sp.edit().putString(URL_KEY, currentURL).commit();
                sp.edit().putString(MD5_KEY, currentMD5).commit();
                sp.edit().putString(SAVE_PATH_KEY, currentSavePath).commit();
                sp.edit().putString(TEMP_PATH_KEY, currentTempPath).commit();
                if (dc == null) {
                    dc = getFileDownload().add(saveFile.getAbsolutePath(), url, myListener);
                } else {
                    dc.resume();
                }
            }
        });
    }

    private static class MD5Error extends JObject {
        public String result = "failed";
        public String url;
        public String error_md5, expect_md5;
    }

    public boolean checkMD5Sum() {
        boolean ret = false;
        try {
            File f = new File(currentSavePath);
            String md5 = Android.getFileMD5(f);
            LogUtils.e("UPGRADE", "md5sum error delete " + currentSavePath + "   md5:" + md5 + "  currentMD5:" + currentMD5);
            ret = currentMD5.equals(md5);

            try {
                LogUtils.SubmitLog log = new LogUtils.SubmitLog();
                log.id = "upgrade_md5_oncheck";
                log.productID = LogUtils.PRODUCTID_APPSTORE;
                if (ret) {
                    log.addParam("result", "success");
                } else {
                    MD5Error error = new MD5Error();
                    error.result = "failed";
                    error.url = currentURL;
                    error.expect_md5 = currentMD5;
                    error.error_md5 = md5;
                    log.addParam("result", error.result);
                    log.addParam("url", error.url);
                    log.addParam("md5", "expect:" + error.expect_md5 + " error:" + error.error_md5);
                    log.addParam("info", error.toJSONString());
                }
                LogUtils.submit(log);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
            ret = false;
        }
        return ret;
    }

    public synchronized void cancel() {
        if (dc != null) {
            dc.discard();
            dc = null;
        }
        try {
            File f;
            if (currentSavePath != null) {
                f = new File(currentSavePath);
                if (f.exists())
                    f.delete();
            }
            if (currentTempPath != null) {
                f = new File(currentTempPath);
                if (f.exists())
                    f.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public synchronized int getStatus() {
        return dc.getStatus();
    }

    private Listener<Void> myListener = new Listener<Void>() {

        @Override
        public void onPreExecute() {
            LogUtils.i("upgrade", "onPreExecute");
            try {
                if (listener != null)
                    listener.onStart();
            } catch (Exception e) {
            }
        }

        @Override
        public void onError(final NetroidError error) {
            LogUtils.i("upgrade", "onError");
            try {
                if (listener != null) {
                    String e = "";
                    if (error != null) {
                        if (error.networkResponse != null) {
                            e = error.networkResponse.statusCode + "|" + error.networkResponse.charset;
                        }
                        e += "  msg:" + error.getMessage();
                    }
                    listener.onError(e);
                }
            } catch (Exception e) {
            }
        }

        @Override
        public void onCancel() {
            LogUtils.i("upgrade", "onCancel");
            try {
                if (listener != null)
                    listener.onCancel();
            } catch (Exception e) {
            }
        }

        @Override
        public void onProgressChange(final long fileSize, final
        long downloadedSize) {
            LogUtils.i("upgrade", "onProgressChange:" + (int) (downloadedSize * 100 / fileSize) + "%     " + downloadedSize + "/" + fileSize);
            try {
                if (listener != null)
                    listener.onProgress((int) (downloadedSize * 100 / fileSize), downloadedSize, fileSize);
            } catch (Exception e) {
            }
        }

        @Override
        public void onSuccess(Void aVoid) {
            LogUtils.i("upgrade", "onSuccess");
            if (!checkMD5Sum()) {
                try {
                    if (listener != null)
                        listener.onError("md5 check failed!");
                } catch (Exception e) {
                }
                try {
                    new File(currentSavePath).delete();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                dc = null;
                return;
            }
            try {
                Runtime.getRuntime().exec("chmod -R 755 " + currentSavePath);
            } catch (Exception e) {
                e.printStackTrace();
            }
            File f = new File(currentSavePath);
            try {
                if (f.exists()) {
                    LogUtils.d("upgrade", " set file r w e  ");
                    f.setReadable(true, false);
                    f.setWritable(true, false);
                    f.setExecutable(true, false);
                }
            } catch (Exception e1) {
                LogUtils.d("upgrade", " set  error!!!!!!!!!");
                e1.printStackTrace();
            }
            try {
                if (listener != null)
                    listener.onSuccess(f);
            } catch (Exception e) {
            }
            dc = null;
        }
    };
}
